﻿// Project: Salient
// http://salient.codeplex.com
// 
// Copyright 2010, Sky Sanders <sky at skysanders.net>
// Dual licensed under the MIT or GPL Version 2 licenses.
// http://salient.codeplex.com/license
// 
// Date: April 25 2010 

#region

using System;

#endregion

namespace Salient.QualityControl
{
    /// <summary>
    /// uUnit
    /// A micro test runner.
    /// 
    /// For those times when just a little is just enough.
    /// 
    /// Simply wraps a void method in a try/catch and writes pass/fail to output delegate.
    /// Find nested a simple assertion class.
    /// 
    /// If you need more, should probably break out the references to nunit.framework.
    ///
    /// </summary>
    public static class UUnit
    {
        #region Delegates

        ///<summary>
        ///</summary>
        ///<param name="message"></param>
        public delegate void OutputDelegate(string message);

        ///<summary>
        ///</summary>
        ///<param name="args"></param>
        public delegate void ParameterizedTestDelegate(params object[] args);

        ///<summary>
        ///</summary>
        public delegate void TestDelegate();

        #endregion

        ///<summary>
        ///</summary>
        public static OutputDelegate Output;

        static UUnit()
        {
            Output = new OutputDelegate(Console.Write);
        }

        ///<summary>
        ///</summary>
        ///<param name="message"></param>
        public static void Write(string message)
        {
            Output(message);
        }

        ///<summary>
        ///</summary>
        ///<param name="message"></param>
        public static void WriteLine(string message)
        {
            Output(message + Environment.NewLine);
        }

        ///<summary>
        ///</summary>
        ///<param name="test"></param>
        ///<param name="args"></param>
        public static void Run(ParameterizedTestDelegate test, params object[] args)
        {
            string name = test.Method.Name;
            try
            {
                test.Invoke(args);
                WriteLine(string.Format("{0} : PASSED", name));
            }
            catch (Exception ex)
            {
                WriteLine(string.Format("{0} : FAILED : {1}", name, ex.Message));
            }
        }

        ///<summary>
        ///</summary>
        ///<param name="test"></param>
        public static void Run(TestDelegate test)
        {
            string name = test.Method.Name;
            try
            {
                test.Invoke();
                WriteLine(string.Format("{0} : PASSED", name));
            }
            catch (Exception ex)
            {
                WriteLine(string.Format("{0} : FAILED : {1}", name, ex.Message));
            }
        }

        #region Nested type: Assert

        /// <summary>
        /// simple assertions. 
        /// If you need more should probably break out the ol' NUnit.
        /// </summary>
        public static class Assert
        {
            ///<summary>
            ///</summary>
            ///<param name="expected"></param>
            ///<param name="actual"></param>
            public static void AreEqual(object expected, object actual)
            {
                AreEqual(expected, actual, "");
            }

            ///<summary>
            ///</summary>
            ///<param name="expected"></param>
            ///<param name="actual"></param>
            ///<param name="message"></param>
            ///<exception cref="Exception"></exception>
            public static void AreEqual(object expected, object actual, string message)
            {
                if (!expected.Equals(actual))
                {
                    throw new Exception(string.Format("{2}: expected {0} but got {1}", expected, actual, message));
                }
            }

            ///<summary>
            ///</summary>
            ///<param name="target"></param>
            public static void IsNull(object target)
            {
                IsNull(target, "");
            }

            ///<summary>
            ///</summary>
            ///<param name="target"></param>
            ///<param name="message"></param>
            ///<exception cref="Exception"></exception>
            public static void IsNull(object target, string message)
            {
                if (target != null)
                {
                    throw new Exception(string.Format("{0}: Expected null but got {1}", message, target));
                }
            }

            ///<summary>
            ///</summary>
            ///<param name="target"></param>
            public static void IsNotNull(object target)
            {
                IsNotNull(target, "");
            }

            ///<summary>
            ///</summary>
            ///<param name="target"></param>
            ///<param name="message"></param>
            ///<exception cref="Exception"></exception>
            public static void IsNotNull(object target, string message)
            {
                if (target == null)
                {
                    throw new Exception(string.Format("{0}: got null", message));
                }
            }

            ///<summary>
            ///</summary>
            ///<param name="expression"></param>
            public static void IsFalse(bool expression)
            {
                IsFalse(expression, "");
            }

            ///<summary>
            ///</summary>
            ///<param name="expression"></param>
            ///<param name="message"></param>
            public static void IsFalse(bool expression, string message)
            {
                AreEqual(false, expression, message);
            }

            ///<summary>
            ///</summary>
            ///<param name="expression"></param>
            public static void IsTrue(bool expression)
            {
                IsTrue(expression, "");
            }

            ///<summary>
            ///</summary>
            ///<param name="expression"></param>
            ///<param name="message"></param>
            public static void IsTrue(bool expression, string message)
            {
                AreEqual(true, expression, message);
            }
        }

        #endregion
    }
}